/* 
 * File:   Integer.cpp
 * Author: Gab'z
 * 
 * Created on 29 mai 2012, 12:26
 */

#include "Integer.h"
#include "../../../exception/ArithmeticException.h"
#include <sstream> 

namespace calculator {

    Integer::Integer(int x) : SimpleNumber(), _x(x) {
    }

    Integer::Integer(const Integer& orig) : SimpleNumber(), _x(orig._x) {
    }

    Integer::~Integer() {
    }

    Integer* Integer::clone() const {
        return new Integer(_x);
    }

    std::string Integer::toString() const {
        std::ostringstream oss;
        oss << _x;
        return oss.str();
    }

    double Integer::value() const {
        return (double) _x;
    }

    Integer& Integer::operator=(const Integer& integer) {
        if (this == &integer) return *this;
        _x = integer._x;
        return *this;
    }

    Integer& Integer::operator+=(const Integer& integer) {
        _x += integer._x;
        return *this;
    }

    Integer& Integer::operator-=(const Integer& integer) {
        _x -= integer._x;
        return *this;
    }

    Integer& Integer::operator*=(const Integer& integer) {
        _x *= integer._x;
        return *this;
    }

    Integer& Integer::operator/=(const Integer& integer) {
        if (integer._x == 0) throw ArithmeticException("Integer divided by 0");
        _x /= integer._x;
        return *this;
    }

    Integer& Integer::operator%=(const Integer& arg) {
        if (arg._x == 0) return *this;
        _x -= arg._x * (_x / arg._x);
        return *this;
    }

    Integer& Integer::pow(const unsigned int& n) {
        if (n == 0) {
            _x = (_x >= 0) ? 1 : -1;
        } else {
            int x = _x;
            for (unsigned int i = 2; i <= n; i++) {
                _x *= x;
            }
        }
        return *this;
    }

    Integer operator+(const Integer& i1, const Integer& i2) {
        Integer integer(i1);
        integer += i2;
        return integer;
    }

    Integer operator-(const Integer& i1, const Integer& i2) {
        Integer integer(i1);
        integer -= i2;
        return integer;
    }

    Integer operator*(const Integer& i1, const Integer& i2) {
        Integer integer(i1);
        integer *= i2;
        return integer;
    }

    Integer operator/(const Integer& i1, const Integer& i2) {
        Integer integer(i1);
        integer /= i2;
        return integer;
    }

    Integer operator%(const Integer& i1, const Integer& i2) {
        Integer integer(i1);
        integer %= i2;
        return integer;
    }

    Integer operator%(const Integer& i1, const unsigned int& n) {
        Integer integer(i1);
        integer.pow(n);
        return integer;
    }
}
